package org.iwidget.desktop.model;
import org.iwidget.desktop.core.IwidgetRepository;
import java.awt.Image;
import java.net.URL;
import javax.swing.ImageIcon;
import org.w3c.dom.*;

/**
 *
 * @author Muhammad Hakim A
 */

public class ElementImage extends ElementUI
{
    class SlideShowThread extends Thread
    {

        public void initialize(boolean isShow, int xDir, int yDir, int conceal, int speed)
        {
            isSliding = true;
            this.isShow = isShow;
            this.xDir = xDir;
            this.yDir = yDir;
            this.speed = speed;
            this.conceal = conceal;
        }

        @Override
        public void run()
        {
            if(isShow)
                showImage();
            else
                hideImage();
        }

        public void showImage()
        {
            while(width != getImageIcon().getIconWidth() || height != getImageIcon().getIconHeight()) 
            {
                if(width != getImageIcon().getIconWidth())
                {
                    if(xDir == -1)
                        xPos--;
                    else
                    if(xDir == 1)
                        xPos++;
                    if(xDir != 0)
                        width++;
                }
                if(height != getImageIcon().getIconHeight())
                {
                    if(yDir == -1)
                        yPos--;
                    else
                    if(yDir == 1)
                        yPos++;
                    if(yDir != 0)
                        height++;
                }
                if(widget != null && widget.getUIComponent() != null)
                    widget.getUIComponent().repaint();
                myComponent.repaint();
                try
                {
                    Thread.sleep(speed);
                }
                catch(Exception e) { }
            }
            isSliding = false;
            isSlid = false;
            xPos = 0;
            yPos = 0;
        }

        public void hideImage()
        {
            boolean isEnded = false;
            while(width != conceal && height != conceal) 
            {
                if(width != conceal)
                {
                    if(xDir == -1)
                        xPos--;
                    else
                    if(xDir == 1)
                        xPos++;
                    if(xDir != 0)
                        width--;
                }
                if(height != conceal)
                {
                    if(yDir == -1)
                        yPos--;
                    else
                    if(yDir == 1)
                        yPos++;
                    if(yDir != 0)
                        height--;
                }
                if(widget != null && widget.getUIComponent() != null)
                    widget.getUIComponent().repaint();
                myComponent.repaint();
                try
                {
                    Thread.sleep(speed);
                }
                catch(Exception e) { }
            }
            isSliding = false;
            isSlid = true;
        }

        private boolean isShow;
        private int xDir;
        private int yDir;
        private int speed;
        private int conceal;

        public SlideShowThread()
        {
        }
    }

    class MoveThread extends Thread
    {

        public void run()
        {
            while(newX != x && newY != y) 
            {
                if(newX < x)
                    x--;
                else
                    x++;
                if(newY < y)
                    y--;
                else
                    y++;
                myComponent.repaint();
                try
                {
                    Thread.sleep(speed);
                }
                catch(Exception e) { }
            }
        }

        private int newX;
        private int newY;
        private int speed;

        public MoveThread(int newX, int newY, int speed)
        {
            this.newX = newX;
            this.newY = newY;
            this.speed = speed;
        }
    }

    class FadeThread extends Thread
    {

        public void run()
        {
            if(startOpacity < endOpacity)
            {
                for(int iCtr = startOpacity; iCtr <= endOpacity; iCtr++)
                {
                    setOpacity(iCtr);
                    myComponent.repaint();
                    try
                    {
                        Thread.sleep(speed);
                    }
                    catch(Exception e) { }
                }

            } else
            {
                for(int iCtr = startOpacity; iCtr >= endOpacity; iCtr--)
                {
                    setOpacity(iCtr);
                    myComponent.repaint();
                    try
                    {
                        Thread.sleep(speed);
                    }
                    catch(Exception e) { }
                }

            }
        }

        private int startOpacity;
        private int endOpacity;
        private int speed;

        public FadeThread(int startOpacity, int endOpacity, int speed)
        {
            this.startOpacity = startOpacity;
            this.endOpacity = endOpacity;
            this.speed = speed;
        }
    }


    public ElementImage()
    {
        alignment = "left";
        opacity = 100;
        rotation = 0.0D;
        src = "";
        xPos = 0;
        yPos = 0;
        xDir = 0;
        yDir = 0;
        isSliding = false;
        isSlid = false;
        name = getId();
    }

    public ElementImage(WidgetElement widget)
    {
        super(widget);
        alignment = "left";
        opacity = 100;
        rotation = 0.0D;
        src = "";
        xPos = 0;
        yPos = 0;
        xDir = 0;
        yDir = 0;
        isSliding = false;
        isSlid = false;
        name = getId();
    }

    public ElementImage(WidgetElement widget, String name)
    {
        super(widget);
        alignment = "left";
        opacity = 100;
        rotation = 0.0D;
        src = "";
        xPos = 0;
        yPos = 0;
        xDir = 0;
        yDir = 0;
        isSliding = false;
        isSlid = false;
        this.name = name;
    }

    public String getAlignment()
    {
        return alignment;
    }

    public void setAlignment(String s)
    {
        if(alignment == null || !alignment.equals(s))
        {
            setChanged();
            alignment = s;
        }
    }

    public ImageIcon getImageIcon()
    {
        return imageData;
    }

    public Image getImage()
    {
        if(imageData != null)
            return imageData.getImage();
        else
            return null;
    }

    public int getOpacity()
    {
        return opacity;
    }

    public void setOpacity(int i)
    {
        if(opacity != i)
        {
            opacity = i;
            if(opacity > 100)
                opacity = 100;
            if(opacity < 0)
                opacity = 0;
            setChanged();
        }
    }

    public double getRotation()
    {
        return rotation;
    }

    public void setRotation(double d)
    {
        if(rotation != d)
        {
            rotation = d;
            setChanged();
        }
    }

    public String getSource()
    {
        return src;
    }

    public void setSource(String string)
    {
        if(src == null || !src.equals(string))
        {
            src = null;
            imageData = null;
            src = string;
            if(string.indexOf("://") > 0)
            {
                URL url = null;
                try
                {
                    url = new URL(string);
                    imageData = new ImageIcon(url);
                }
                catch(Exception e)
                {
                    widget.getParent().getDebugFrame().addText("SYSTEM:Error:Could not load image URL:" + widget.getName() + ":" + string);
                }
                url = null;
            } else
            {
                byte bytes[] = IwidgetRepository.getInstance().getObject(widget.getName(), src);
                try
                {
                    imageData = new ImageIcon(bytes);
                }
                catch(Exception ex)
                {
                    widget.getParent().getDebugFrame().addText("SYSTEM:Error:Could not load image:" + widget.getName() + ":" + string);
                }
                bytes = null;
            }
            if(imageData != null)
            {
                width = imageData.getIconWidth();
                height = imageData.getIconHeight();
                setChanged();
                if(myComponent != null)
                    myComponent.setSize(width, height);
            }
        }
    }

    public int getXPos()
    {
        return xPos;
    }

    public void setXPos(int i)
    {
        xPos = i;
    }

    public int getYPos()
    {
        return yPos;
    }

    public void setYPos(int i)
    {
        yPos = i;
    }

    public void parse(Node node)
        throws Exception
    {
        NamedNodeMap map = node.getAttributes();
        for(int iCtr = 0; iCtr < map.getLength(); iCtr++)
        {
            Node attr = map.item(iCtr);
            parseHelper(attr.getNodeName(), attr.getNodeValue(), null);
        }

        NodeList nodes = node.getChildNodes();
        for(int iCtr = 0; iCtr < nodes.getLength(); iCtr++)
        {
            Node childNode = nodes.item(iCtr);
            String nodeName = childNode.getNodeName();
            String nodeValue = childNode.getNodeValue();
            if(childNode.getFirstChild() != null)
                parseHelper(nodeName, childNode.getFirstChild().getNodeValue(), childNode);
        }

        if(getName() == null || getName().length() == 0)
        {
            widget.getParent().getDebugFrame().addText("SYSTEM:Error:Image element is not named");
            setName("Unknown_" + System.currentTimeMillis());
        }
    }

    private void parseHelper(String nodeName, String value, Node childNode)
    {
        if(nodeName.equals("alignment"))
            setAlignment(value);
        else
        if(nodeName.equals("cursor"))
            setCursor(value);
        else
        if(nodeName.equals("height"))
            setHeight(Integer.parseInt(value));
        else
        if(nodeName.equals("name"))
            setName(value);
        else
        if(nodeName.equals("opacity"))
            setOpacity(Integer.parseInt(value));
        else
        if(nodeName.equals("owner"))
            setOwner(value);
        else
        if(nodeName.equals("rotation"))
            setRotation(Double.parseDouble(value));
        else
        if(nodeName.equals("source"))
            setSource(value);
        else
        if(nodeName.equals("tooltip"))
            setTooltip(value);
        else
        if(nodeName.equals("visible"))
        {
            if(value.equals("true"))
                setVisible(true);
            else
                setVisible(false);
        } else
        if(nodeName.equals("width"))
            setWidth(Integer.parseInt(value));
        else
        if(nodeName.equals("x"))
            setX(Integer.parseInt(value));
        else
        if(nodeName.equals("y"))
            setY(Integer.parseInt(value));
        else
        if(nodeName.startsWith("on"))
            addAction(nodeName, addChildAction(nodeName, childNode));
    }

    public void fade(int startOpacity, int endOpacity)
    {
        fade(startOpacity, endOpacity, 20);
    }

    public void fade(int startOpacity, int endOpacity, int speed)
    {
        if(startOpacity > 100 || startOpacity < 0)
        {
            startOpacity = 100;
            widget.getParent().getDebugFrame().addText("SYSTEM:Error:Fade startOpacity out of range for image:" + getName());
        }
        if(endOpacity > 100 || endOpacity < 0)
        {
            endOpacity = 0;
            widget.getParent().getDebugFrame().addText("SYSTEM:Error:Fade endOpacity out of range for image:" + getName());
        }
        if(speed > 100 || speed < 0)
        {
            speed = 50;
            widget.getParent().getDebugFrame().addText("SYSTEM:Error:Fade speed out of range for image:" + getName());
        }
        FadeThread f = new FadeThread(startOpacity, endOpacity, speed);
        f.setPriority(1);
        f.start();
    }

    public void moveTo(int newX, int newY, int speed)
    {
        if(newX > widget.getWindowJS().getWidth() || x < 0)
        {
            newX = 0;
            widget.getParent().getDebugFrame().addText("SYSTEM:Error:moveTo X out of range for image:" + name);
        }
        if(newY > widget.getWindowJS().getHeight() || newY < 0)
        {
            newY = 0;
            widget.getParent().getDebugFrame().addText("SYSTEM:Error:moveTo Y out of range for image:" + name);
        }
        if(speed > 100 || speed < 0)
        {
            speed = 50;
            widget.getParent().getDebugFrame().addText("SYSTEM:Error:moveTo speed out of range for image:" + name);
        }
        MoveThread f = new MoveThread(newX, newY, speed);
        f.setPriority(1);
        f.start();
    }

    public void slideShow()
    {
        xDir = -xDir;
        yDir = -yDir;
        while(isSliding) 
            try
            {
                Thread.sleep(100L);
            }
            catch(Exception e) { }
        if(isSlid)
        {
            SlideShowThread f = new SlideShowThread();
            f.initialize(true, xDir, yDir, 0, speed);
            f.setPriority(1);
            f.start();
        }
    }

    public void slideHide(String dir, int conceal, int speed)
    {
        this.speed = speed;
        if(conceal < 0)
        {
            conceal = 0;
            widget.getParent().getDebugFrame().addText("SYSTEM:Error:slide conceal out of range for image:" + name);
        }
        if(dir.indexOf("left") >= 0)
            xDir = -1;
        else
        if(dir.indexOf("right") >= 0)
            xDir = 1;
        if(dir.indexOf("up") >= 0)
            yDir = -1;
        else
        if(dir.indexOf("down") >= 0)
            yDir = 1;
        if(speed > 100 || speed < 0)
        {
            speed = 50;
            widget.getParent().getDebugFrame().addText("SYSTEM:Error:slide speed out of range for image:" + name);
        }
        while(isSliding) 
            try
            {
                Thread.sleep(100L);
            }
            catch(Exception e) { }
        if(!isSlid)
        {
            SlideShowThread f = new SlideShowThread();
            f.initialize(false, xDir, yDir, conceal, speed);
            f.setPriority(1);
            f.start();
        }
    }

    private String alignment;
    private ImageIcon imageData;
    private int opacity;
    private double rotation;
    private String src;
    private int xPos;
    private int yPos;
    private int xDir;
    private int yDir;
    private int speed;
    private boolean isSliding;
    private boolean isSlid;

}